package runtimeapi

import (
    "go-os-qemu/pkg/vga"
)

// simple helpers
func printDec(n int) {
    if n == 0 { vga.Print("0"); return }
    var buf [16]byte
    i := len(buf)
    m := n
    if m < 0 { vga.Print("-"); m = -m }
    for m > 0 && i > 0 {
        i--
        buf[i] = byte('0' + (m % 10))
        m /= 10
    }
    for ; i < len(buf); i++ { vga.Print(string(rune(buf[i]))) }
}

func printHexNibble(n uint8) {
    d := n & 0x0F
    if d < 10 { vga.Print(string(rune('0' + d))) } else { vga.Print(string(rune('A' + (d - 10)))) }
}
func printHex32(n uint32) {
    for i := 0; i < 8; i++ {
        shift := uint(28 - i*4)
        printHexNibble(uint8((n >> shift) & 0x0F))
    }
}

// Exec executes a runtime method by name with string arguments.
// Supported methods:
//  - print <text>
//  - println <text>
//  - dec <n>
//  - hex <n>
//  - color <fg> <bg>
//  - clear
//  - newline
func Exec(name string, args []string) bool {
    switch name {
    case "print":
        if len(args) < 1 { return false }
        vga.Print(args[0])
        return true
    case "println":
        if len(args) < 1 { return false }
        vga.Print(args[0])
        vga.Println("")
        return true
    case "dec":
        if len(args) < 1 { return false }
        n, ok := parseInt(args[0]); if !ok { return false }
        printDec(n)
        return true
    case "hex":
        if len(args) < 1 { return false }
        n, ok := parseInt(args[0]); if !ok { return false }
        printHex32(uint32(n))
        return true
    case "color":
        if len(args) < 2 { return false }
        fg, ok1 := parseInt(args[0])
        bg, ok2 := parseInt(args[1])
        if !ok1 || !ok2 { return false }
        vga.SetColor(byte(fg), byte(bg))
        return true
    case "clear":
        vga.Clear(); return true
    case "newline":
        vga.Println(""); return true
    default:
        return false
    }
}

// Eval parses a very small subset of Go-like function calls, e.g.:
// println("Hello"), print("Hi"), dec(123), hex(48879), color(10,0), clear(), newline()
func Eval(code string) bool {
    // trim leading spaces
    i := 0
    for i < len(code) && (code[i] == ' ' || code[i] == '\t') { i++ }
    if i >= len(code) { return false }
    // parse identifier
    start := i
    for i < len(code) && ((code[i] >= 'a' && code[i] <= 'z') || (code[i] >= 'A' && code[i] <= 'Z')) { i++ }
    name := code[start:i]
    // expect '('
    for i < len(code) && code[i] == ' ' { i++ }
    if i >= len(code) || code[i] != '(' { return false }
    i++
    // parse arguments (strings in quotes or numbers), separated by commas
    var args []string
    for i < len(code) {
        // skip spaces
        for i < len(code) && code[i] == ' ' { i++ }
        if i >= len(code) { break }
        if code[i] == ')' { i++; break }
        if code[i] == '"' {
            i++
            start = i
            for i < len(code) && code[i] != '"' { i++ }
            if i > start { args = append(args, code[start:i]) }
            if i < len(code) && code[i] == '"' { i++ }
        } else {
            start = i
            for i < len(code) && code[i] != ',' && code[i] != ')' && code[i] != ' ' { i++ }
            if i > start { args = append(args, code[start:i]) }
        }
        // skip spaces
        for i < len(code) && code[i] == ' ' { i++ }
        if i < len(code) && code[i] == ',' { i++ }
    }
    return Exec(name, args)
}

func parseInt(s string) (int, bool) {
    if len(s) == 0 { return 0, false }
    neg := false
    i := 0
    if s[0] == '-' { neg = true; i++ }
    val := 0
    for i < len(s) {
        c := s[i]
        if c < '0' || c > '9' { return 0, false }
        val = val*10 + int(c-'0')
        i++
    }
    if neg { val = -val }
    return val, true
}